/******************************************
 * Nombre del archivo: Main.java
 * Universidad del Valle de Guatemala
 * Curso: Algoritmos y Estructura de Datos
 * Autores:
 *      * Martín Guzmán     08041
 *      * David Hsieh       08225
 *      * Eduardo Mejicano  08058
 *      * Kevin Sánchez     08302
 * Fecha: 16 de agosto de 2009
 * Descripción:
*******************************************/

import java.util.Scanner;
import java.util.ArrayList;
import java.util.Random;

public class Main {

    private static String ultima_instruccion="";
    private static ArrayList<Atomo> instrucciones = new ArrayList<Atomo>();
    private static Scanner scan = new Scanner(System.in);
    private static int lineas=1;

    /*****************************************
     * Método: main
     * Autor: Martín Guzmán
     * Uso: Constructor de la clase Main.
     *      Inicio del programa.
     *****************************************/
    public static void main(String[] args) throws Error{
        System.out.println("  i i i i i i i       ooooo    o        ooooooo   ooooo   ooooo\n"
                          +"  I I I I I I I      8     8   8           8     8     o  8    8\n"
                          +"  I  \\ '+' /  I      8         8           8     8        8    8\n"
                          +"   \\  '-+-'  /       8         8           8      ooooo   8oooo\n"
                          +"    '-__|__-'        8         8           8           8  8\n"
                          +"        |            8     o   8           8     o     8  8\n"
                          +"  ------+------       ooooo    8oooooo  ooo8ooo   ooooo   8");
        System.out.println("\nWelcome to GNU CLISP INTERPRETER 0.00.000001 (2009-08-16) <http://code.google.com/p/aed-p01/>");
        System.out.println("Type (help) and hit Enter for context help. Or type (exit) to quit.\n");
        Funcion nueva_funcion= new Funcion("");



        At_Lista lista_atomos;

        String instruccion_temporal="";
        do{
            instruccion_temporal = Prompt();
            instruccion_temporal=instruccion_temporal.toUpperCase();
            //ciclo para quitar los espacios en blanco del inicio
            while(true){
                //System.out.println("."+instruccion_temporal+".");
                if(instruccion_temporal.startsWith(" ")){
                    instruccion_temporal=instruccion_temporal.substring(1,instruccion_temporal.length());
                }
                else
                    break;
            }
            if (instruccion_temporal.compareToIgnoreCase("(exit)")==0)//revisar si debe terminar ejecución
                break;
            if (instruccion_temporal.compareToIgnoreCase("(help)")==0)//revisar si debe meterse al help
                Help();
            else if(instruccion_temporal.isEmpty()){
                    //para que simplemente repita y no haga nada
            }
            else if (Lista_Variables.getValor(instruccion_temporal) != null) {//revisa si ingresó una variable directamente
                System.out.println(Lista_Variables.getValor(instruccion_temporal));
            }else if (Cantidad_parentesis(instruccion_temporal)==false){
                System.out.println("Error. Missing parentheses.");
            }
            else{
                instruccion_temporal=Quitar_espacios(instruccion_temporal);
                //System.out.println("ANTES DE EMPEZAR: "+instruccion_temporal);//TODO quitar esto //debuguear

                // Si está definiendo una función
                if(instruccion_temporal.startsWith("(,DEFUN")){
                    try{
                        //System.out.println("Nueva función");
                        nueva_funcion= new Funcion(instruccion_temporal);
                    }catch(Exception exp){
                        System.out.println("Funtion sintaxis incorrect");
                    }
                }

                // si empieza haciendo una lista literal como por ejemplo: '(1 2 3)
                else if(instruccion_temporal.startsWith("'")){
                    At_Lista_Literal literal_list = new At_Lista_Literal(instruccion_temporal);
                    System.out.println(literal_list.Obtener_valor());
                }
                else{
                    //evalúa una lista normal
                    lista_atomos = new At_Lista(instruccion_temporal.substring(2, instruccion_temporal.length()-2));
                    if (lista_atomos.lista.size()!=0){
                        System.out.println(lista_atomos.Obtener_valor());//calcula el resultado de la operación
                    }
                    else{
                        System.out.println("Error. Invalid expression. (esto está dentro del main)");//Corregir mensaje
                    }
                }
            }
        } while(true);
        
    }

    /*****************************************
     * Método: Prompt
     * Autor: Martín Guzmán
     * Uso: Despliega el prompt para que
     *      ingrese las instrucciones a
     *      ejecutar.
     * Retorno: instrucción ingresada.
     *****************************************/
    public static String Prompt(){
        System.out.print("["+lineas+"]>> ");
        lineas++;
        return scan.nextLine();
    }

    /*****************************************
     * Método: Cantidad_parentesis
     * Autor: Martín Guzmán
     * Uso: Maneja la cantidad de paréntesis
     * Retorno: booleano diciendo si está
     *      correcta o no la cantidad de
     *      paréntesis.
     *****************************************/
    public static boolean Cantidad_parentesis(String instruccion){
        int cant_paren_abierto=0;
        int cant_paren_cerrado=0;
        //ciclo que revisa cantidad de paréntesis
        for(int i=0;i<instruccion.length();i++){
            if (instruccion.charAt(i)=='(')
                cant_paren_abierto++;
            else if (instruccion.charAt(i)==')')
                cant_paren_cerrado++;
        }
        //compara si la cantidad de paréntesis son iguales
        if (cant_paren_abierto==cant_paren_cerrado)
            return true;
        return false;
    }

    /*****************************************
     * Método: Quitar espacios
     * Autor: Martín Guzmán
     * Uso: quita espacios inservibles
     * Retorno: cadena sin espacios inservibles
     *          y separando los átomos por
     *          comas
     *****************************************/
    public static String Quitar_espacios(String instruccion){
        String retorno="";
        String[] arreglo_temporal=instruccion.split(" ");
        ArrayList<String> arreglo_temporal_2= new ArrayList<String>();
        for(int i=0;i<arreglo_temporal.length;i++){
            arreglo_temporal_2.add(arreglo_temporal[i]);
        }
        //System.out.println("Tamaño: "+arreglo_temporal_2.size());//TODO quitar esto

        //para quitar los espacios en blanco
        for(int i=0;i<arreglo_temporal_2.size();i++){
            if(arreglo_temporal_2.isEmpty()){
                arreglo_temporal_2.remove(i--);
            }
        }

        //lo agrega a una cadena separando los operandos por coma
        for(int i=0;i<arreglo_temporal_2.size();i++){
            retorno+=arreglo_temporal_2.get(i)+",";
        }

        //le agrega comas a donde haga falta: ,(, ,),
        for(int i=0;i<retorno.length()-1;i++){
            if (retorno.charAt(i)=='(' && retorno.charAt(i+1)!=','){
                retorno=retorno.substring(0, i+1)+","+retorno.substring(i+1, retorno.length());
            }
            if (retorno.charAt(i)==')' && retorno.charAt(i+1)!=','){
                retorno=retorno.substring(0, i+1)+","+retorno.substring(i+1, retorno.length());
            }
            if (retorno.charAt(i)!=',' && retorno.charAt(i+1)=='('){
                retorno=retorno.substring(0, i+1)+","+retorno.substring(i+1, retorno.length());
            }
            if (retorno.charAt(i)!=',' && retorno.charAt(i+1)==')'){
                retorno=retorno.substring(0, i+1)+","+retorno.substring(i+1, retorno.length());
            }
        }
        while(retorno.contains(",,")){
            retorno=retorno.replaceAll(",,",",");
        }
        
        return retorno.substring(0, retorno.length()-1);//hasta ahí para quitar la última coma
    }
    
    /*****************************************
     * Método: Help
     * Autor: Martín Guzmán
     * Uso: Ayuda para el usuario.
     * Retorno: instrucciones para usos.
     *****************************************/
    public static void Help(){
        System.out.print("helping..!");//TODO arreglar la ayuda
    }

}
